﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

using Mommosoft.ExpertSystem;

namespace NUS.ISS.SRKBS.BLL
{
    public static class RegulatoryRuleEngine
    {
        private static Mommosoft.ExpertSystem.Environment _theEnv = new Mommosoft.ExpertSystem.Environment();

        public static void Init()
        {
            try {
                _theEnv.Clear();
                _theEnv = new Mommosoft.ExpertSystem.Environment();
                ConsoleTraceListener tl = new ConsoleTraceListener();
                _theEnv.AddRouter(new DebugRouter());
                _theEnv.Load(@"D:\SRKBS.clp");
                _theEnv.Reset();                            
            }
            catch (Exception e)
            {
                Console.WriteLine("Error whil loading the CLIPS file." + e.Message);
            }
        }

        public static ClipState GetState()
        {
            ClipState nextstate = new ClipState();

            try {
                _theEnv.Run();               

                // Get the state-list.
                String evalStr = "(find-all-facts ((?f state-list)) TRUE)";
                using (FactAddressValue allFacts = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalStr))[0])
                {
                    string currentID = allFacts.GetFactSlot("current").ToString();
                    evalStr = "(find-all-facts ((?f UI-state)) " +
                                   "(eq ?f:id " + currentID + "))";
                }

                using (FactAddressValue evalFact = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalStr))[0])
                {
                        string state = evalFact.GetFactSlot("state").ToString();
                        nextstate.state = state;

                        string display = (SymbolValue)evalFact.GetFactSlot("display");
                        nextstate.display = display;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.Message);
            }
            return nextstate;
        }

        public static void NextState()
        {   
            String evalStr = "(find-all-facts ((?f state-list)) TRUE)";
            using (FactAddressValue f = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalStr))[0])
            {
                string currentID = f.GetFactSlot("current").ToString();
                _theEnv.AssertString("(next " + currentID + ")");
            }
        }

        public static void PrevState()
        {
            String evalStr = "(find-all-facts ((?f state-list)) TRUE)";
            using (FactAddressValue f = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalStr))[0])
            {
                string currentID = f.GetFactSlot("current").ToString();
                _theEnv.AssertString("(prev " + currentID + ")");
            }
        }

        public static RegulatoryModel RetriveRegulatory()
        {
            RegulatoryModel reg = new RegulatoryModel();

            _theEnv.Run();
            String evalResult = "(find-all-facts ((?f application)) TRUE)";

            try
            {
                using (FactAddressValue f = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalResult))[0])
                {
                    reg.ProjectName = (SymbolValue)f.GetFactSlot("project");
                }
            }
            catch { }

            return reg;
        }

        public static void AssertAttributes(List<RegulatoryAttribute> regulatoryAttribute)
        {
            bool retVal = false;

            foreach (RegulatoryAttribute strAttrib in regulatoryAttribute)
            {
                if (strAttrib.IsCLIPSNotifyRequired)
                {
                    if (strAttrib.IsString)
                    {
                        retVal = DoActionForStringAndCheckFinal(strAttrib.AttributeName, strAttrib.AttributeValue);
                    }
                    else
                    {
                        retVal = DoActionForValueAndCheckFinal(strAttrib.AttributeName, strAttrib.AttributeValue);
                    }
                }
                else
                {
                    if (strAttrib.IsString)
                    {
                        DoActionForString(strAttrib.AttributeName, strAttrib.AttributeValue);
                    }
                    else
                    {
                        DoActionForValue(strAttrib.AttributeName, strAttrib.AttributeValue);
                    }
                }

                if (retVal)
                    break;
            }
        }

        private static void DoActionForString(string strAttribute, string strAttributeValue)
        {
            _theEnv.AssertString(string.Format("({0} \"{1}\")", strAttribute, strAttributeValue));
        }

        private static bool DoActionForStringAndCheckFinal(string strAttribute, string strAttributeValue)
        {
            _theEnv.AssertString(string.Format("({0} \"{1}\")", strAttribute, strAttributeValue));
            return CheckForFinal();
        }

        private static void DoActionForValue(string strAttribute, string strAttributeValue)
        {
            _theEnv.AssertString(string.Format("({0} {1})", strAttribute, strAttributeValue));
        }

        private static bool DoActionForValueAndCheckFinal(string strAttribute, string strAttributeValue)
        {
            _theEnv.AssertString(string.Format("({0} {1})", strAttribute, strAttributeValue));
            return CheckForFinal();
        }

        private static bool CheckForFinal()
        {
            bool retVal = false;

            _theEnv.Run();

            String evalStr = "(find-all-facts ((?f state-list)) TRUE)";
            using (FactAddressValue allFacts = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalStr))[0])
            {
                string currentID = allFacts.GetFactSlot("current").ToString();
                evalStr = "(find-all-facts ((?f UI-state)) " + "(eq ?f:id " + currentID + "))";
            }

            using (FactAddressValue evalFact = (FactAddressValue)((MultifieldValue)_theEnv.Eval(evalStr))[0])
            {
                string state = evalFact.GetFactSlot("state").ToString();

                if (state.Equals("final"))
                {
                    retVal = true;
                }
            }

            return retVal;
        }
        
    }
    
}
